/*
 *  AObject.h
 *  
 *
 *  Created by Peter on 23.02.12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */
#ifndef A_OBJECT_H
#define A_OBJECT_H

#include <iostream>
#include <string>

#include "TrCompat.h"

class AStream;
class AObjDoc;

/*
 * Base class that provides the foundations for serializing objects. In order to
 * provide that functionality, we also roughly mirror what I assume is Avid's RTTI model.
 * TODO: Add a virtual destructor!!!
 */
class AObject
{
	
public:
	
	/*----- enums & typedefs -----*/
	
	// PClass Id (FourCC that uniquely identifies a class)
	typedef UInt32 PCID;
	
	/*----- member functions -----*/
	
	// These are automatically implemented by the A_DECLARE_CLASS macro
	virtual PCID getClassId() const;
	virtual std::string getClassName() const;
	virtual bool isInstanceOf( const std::string& className ) const;
	
	// Serializing the object to or from a stream. The pointer to AObjDoc is
	// required to resolve pointers.
	virtual void readFromStream( AStream& str, const AObjDoc& objD );
	virtual void writeToStream( AStream& str ) const;
	
	// Dumping to a debug console
	virtual void dump( std::ostream& str ) const;
	
};

// Use this to outpur a PCID to a stream for debugging
void writePcidToStream( std::ostream& str, AObject::PCID pcid );	
// Use this to make a string from a FOURCC
std::string pcidToString( AObject::PCID pcid );

// This implements something similar to Avid's RTTI model
// TODO: Separate this out into a A_DECLARE_CLASS and an A_IMPLEMENT_CLASS macro
// TODO: Make the class name return a const char* (more efficient)
#define A_DECLARE_CLASS( pcid, className, baseClass ) \
	typedef baseClass BaseClass; \
	static const AObject::PCID _pcid; \
	virtual AObject::PCID getClassId() const { return _pcid; } \
	virtual std::string getClassName() const; \
	virtual bool isInstanceOf( const std::string& clsName ) const;

#define A_IMPLEMENT_CLASS( pcid, className, baseClass ) \
	\
	const AObject::PCID className::_pcid = pcid; \
	\
	bool className::isInstanceOf( const std::string& clsName ) const \
	{ \
		if( clsName == #className ) \
            return true; \
		\
		return BaseClass::isInstanceOf( clsName ); \
	} \
	\
	std::string className::getClassName() const \
	{ \
		return #className; \
	}



/*inline AStream& operator >> ( AStream& lhs, AObject& obj )
{
	obj.readFromStream( lhs );
	return lhs;
}

inline AStream& operator << ( AStream& lhs, const AObject& obj )
{
	obj.writeToStream( lhs );
	return lhs;
}*/

#endif /*Inclusion Guard*/